#ifndef _DUKTAPEMANAGER_H_INCLUDE_
#define _DUKTAPEMANAGER_H_INCLUDE_

#include "dukglue/dukglue.h"

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdexcept>

// 前置声明注册函数
template<typename T>
void register_class_external(duk_context* ctx);

#define DUKGLUE_OBJECT(T) \
friend void register_class_external<T>(duk_context* ctx);

// 类注册宏
#define DUKGLUE_EXTERNAL_REGISTER(T) \
template<> void register_class_external<T>(duk_context* ctx)

// 注册构造函数的宏
#define DUKGLUE_REGISTER_CONSTRUCTOR(ctx, className, ...) \
    dukglue_register_constructor<className, ##__VA_ARGS__>(ctx, #className)

// 注册方法的宏
#define DUKGLUE_REGISTER_METHOD(ctx, className, method, jsName) \
    dukglue_register_method(ctx, &className::method, jsName)

// 注册属性的宏
#define DUKGLUE_REGISTER_PROPERTY(ctx, className, getter, setter, jsName) \
    dukglue_register_property(ctx, &className::getter, &className::setter, jsName)

// 注册只读属性的宏
#define DUKGLUE_REGISTER_READONLY_PROPERTY(ctx, className, getter, jsName) \
    dukglue_register_property(ctx, &className::getter, nullptr, jsName)

// 注册静态方法的宏
#define DUKGLUE_REGISTER_STATIC_METHOD(ctx, className, method, jsName) \
    dukglue_register_static_method(ctx, &className::method, jsName)

// 设置基类的宏
#define DUKGLUE_SET_BASE_CLASS(ctx, BaseClass, DerivedClass) \
    dukglue_set_base_class<BaseClass, DerivedClass>(ctx)

// 完整的类注册宏（包含继承关系）
#define DUKGLUE_REGISTER_CLASS(ctx, ClassName, ...) \
    DUKGLUE_REGISTER_CONSTRUCTOR(ctx, ClassName, ##__VA_ARGS__)

#define DUKGLUE_REGISTER_DERIVED_CLASS(ctx, ClassName, BaseClass, ...) \
    DUKGLUE_REGISTER_CONSTRUCTOR(ctx, ClassName, ##__VA_ARGS__); \
    DUKGLUE_SET_BASE_CLASS(ctx, BaseClass, ClassName)

class DuktapeManager
{
public:
    DuktapeManager();
    ~DuktapeManager();

    /// 初始DukTape
    bool initDukTape(void);
    /// 卸载DukTape
    void cleanDukTape(void);
    /// 得到DukContent
    inline duk_context* getContent(void) { return m_ctx; }
    /// 执行脚本
    void runScript(const char* scriptStr);

    template<typename Enum>
    void registerEnumToDukTape(const char* name, std::initializer_list<std::pair<const char*, Enum>> values)
    {
        if (m_ctx == NULL) {
            throw std::runtime_error("Duktape context not initialized");
        }

        try {
            duk_push_object(m_ctx);
            for (const auto& [key, value] : values) {
                duk_push_int(m_ctx, static_cast<int>(value));
                duk_put_prop_string(m_ctx, -2, key);
            }
            duk_put_global_string(m_ctx, name);
        } catch (const std::exception& e) {
            duk_set_top(m_ctx, 0);  // 安全清理堆栈
            throw std::runtime_error(std::string("Failed to register enum: ") + e.what());
        }
    }
    // 可变参数模板版本：支持任意数量和类型的参数
    template<typename... Args>
    std::string execute_function_callback(const char* function, Args&&... args) {
        return execute_function_callback_impl(function, std::forward<Args>(args)...);
    }
    /// 注册一个类到DukTape
    template<typename T>
    void registerClassToDukTape(void)
    {
        if (m_ctx == NULL) {
            throw std::runtime_error("Duktape context not initialized");
        }

       try {
            register_class_external<T>(m_ctx);
        } catch (const std::exception& e) {
           duk_set_top(m_ctx, 0);  // 安全清理堆栈
           throw std::runtime_error(std::string("Failed to register enum: ") + e.what());
       }
    }
    /// 注册一个对象到DukTape
    template <typename T>
    void registerObjectToDukTape(const T& obj,const char* name)
    {
        if (m_ctx == nullptr) {
            throw std::runtime_error("Duktape context not initialized");
        }

        if (name == nullptr || strlen(name) == 0) {
            throw std::invalid_argument("Invalid object name");
        }

        try {
            // 检查是否已存在同名全局变量
            duk_push_global_object(m_ctx);
            if (duk_has_prop_string(m_ctx, -1, name)) {
                duk_pop(m_ctx);  // 弹出全局对象
                throw std::runtime_error(std::string("Global variable '") + name + "' already exists");
            }
            duk_pop(m_ctx);  // 弹出全局对象

            // 注册全局对象
            dukglue_register_global(m_ctx, obj, name);

            // 验证注册是否成功
            duk_push_global_object(m_ctx);
            if (!duk_has_prop_string(m_ctx, -1, name)) {
                duk_pop(m_ctx);  // 弹出全局对象
                throw std::runtime_error(std::string("Failed to register object '") + name + "'");
            }
            duk_pop(m_ctx);  // 弹出全局对象

        } catch (const std::exception& e) {
            // 确保堆栈平衡
            duk_set_top(m_ctx, 0);
            throw;
        }
    }

private:
    // 实际实现函数
    template<typename... Args>
    std::string execute_function_callback_impl(const char* function, Args&&... args) {
        if (m_ctx == nullptr || function == nullptr || function[0] == '\0') {
            return "";
        }

        try {
            // 检查函数是否存在
            if (!duk_get_global_string(m_ctx, function)) {
                throw std::runtime_error(std::string("Function not found: ") + function);
            }

            // 压入所有参数
            push_args(std::forward<Args>(args)...);

            // 调用函数
            if (duk_pcall(m_ctx, sizeof...(Args)) != 0) {
                qDebug()<<duk_safe_to_string(m_ctx, -1);
                throw std::runtime_error(duk_safe_to_string(m_ctx, -1));
            }

            // 获取返回值
            const char* ret_val = duk_get_string(m_ctx, -1);
            std::string result = ret_val ? ret_val : "";
            duk_pop(m_ctx); // 弹出返回值

            return result;
        } catch (const std::exception& e) {
            duk_set_top(m_ctx, 0);  // 安全清理堆栈
            std::cerr << "Duktape Error: " << e.what() << std::endl;
            return "";
        }
    }

    // 递归终止条件：参数包为空时什么也不做
    void push_args() {}

    // 递归展开参数包，逐个压栈
    template<typename T, typename... Args>
    void push_args(T&& arg, Args&&... args) {
        push_single_arg(std::forward<T>(arg));
        push_args(std::forward<Args>(args)...);
    }

    // 处理单个参数，根据类型调用不同的 Duktape API
    template<typename T>
    void push_single_arg(T&& arg) {
        using Type = std::decay_t<T>;

        if constexpr (std::is_same_v<Type, std::string> || std::is_same_v<Type, const char*>) {
            duk_push_string(m_ctx, std::forward<T>(arg));
        } else if constexpr (std::is_integral_v<Type>) {
            if constexpr (std::is_same_v<Type, bool>) {
                duk_push_boolean(m_ctx, arg);
            } else {
                duk_push_number(m_ctx, static_cast<duk_double_t>(arg));
            }
        } else if constexpr (std::is_floating_point_v<Type>) {
            duk_push_number(m_ctx, static_cast<duk_double_t>(arg));
        } else if constexpr (std::is_null_pointer_v<Type>) {
            duk_push_null(m_ctx);
        } else if constexpr (std::is_pointer_v<Type>) {
            if (arg == nullptr) {
                duk_push_null(m_ctx);
            } else {
                dukglue_push(m_ctx, arg);
            }
        } else {
            static_assert(std::is_pointer_v<Type>, "Unsupported argument type");
        }
    }

private:
    duk_context* m_ctx;
};

#endif // DUKTAPEMANAGER_H
